Angular - Featured and Presentation Component

In this article, lets learn the featured and presentation components. It may also be refered as

  • Smart and Dump Components
  • Featured and Presentation Components

Featured Components are the components which will be acting as the parent component holding all other components which can be referred to as child components. The featured components are the components which are responsible for gathering data from different services and providing the data to its child component. This performs smart work by collecting data, transferring data to its child components and taking actions based on the event raised by its child components.

Presentation Components

These are the components, which receives the data from the featured components and use those data to populate a list or any other operation with those data. These components are responsible only to present information provided by the featured component. These components does not perform any business logic. If needed to perform any business logic it has to communicate with the featured component by raising an event and notifying the parent component.

Normally presentation component get data from featured component through @Input() and raises an event using @Output() to notify the featured component to perform any action.

Let's start with an example program

Create a new angular project

Create a new angular application using

ng new angular-app

Enter into the project using

cd angular-app

Once the application has been created using angular cli command, to check the initial result of the application enter.

ng serve --o

Create a service and modify the code

ng g s services/product

This will create a ProductService in services folder with some boilerplate code. Modify the code as below.

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class ProductService {
  private products: { name: string }[] = [
    { name: 'Apple' },
    { name: 'Asus' },
    { name: 'HP' },
    { name: 'Acer' }
  ];
  constructor() { }

  getProducts() {
    return this.products;
  }

  removeProduct(productName: string) {
    const index = this.products.findIndex((value) => {
      return value.name === productName;
    });
    console.log(index);
    if (index > -1) {
      this.products.splice(index, 1);
    }
  }
}

The ProductService will have a list of products and will perform 2 functionality with getProducts() function and removeProduct() function.

  • getProducts() - Will return the list of products
  • removeProduct() - Will remove the product from the list based on the product name.

Create a Presentation Component

Enter the following angular cli command to create a component to act as presentation component.

ng g c product

After the component is created, modify the product.component.ts file with product @Input() and select @Output().

import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'app-product',
  templateUrl: './product.component.html',
  styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {

  @Input() product;
  // tslint:disable-next-line: no-output-native
  @Output() select = new EventEmitter<any>();
  constructor() { }

  ngOnInit() {
  }

  removeProduct() {
    this.select.emit(this.product.name);
  }
}

Modify the product.component.html file with the following code.

<p>
  <button (click)='removeProduct()'>Remove</button>
  Product Name : <span>{{product.name}} </span>
</p>

The product @Input() will receive the product name from its parent(Featured) component which will be displayed in its template insida a p tag.

When clicking on Remove button, it will call the removeProduct() function. The removeProduct() function will use the select event emitter to emit an event to its parent with the name of the product.

Create a featured component, ProductListComponent to list the products.

ng g c product-list

Once the component is created, modify the product-list.component.ts file code to get the product list from ProductService.

import { Component, OnInit } from '@angular/core';
import { ProductService } from '../services/product.service';
@Component({
  selector: 'app-product-list',
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit {

  products: { name: string }[];
  constructor(private productService: ProductService) { }

  ngOnInit() {
    this.products = this.productService.getProducts();
    console.log(this.products);
  }

  removeProduct(productName) {
    this.productService.removeProduct(productName);
  }
}

Here, we have injected the ProductService to the constructor and called the getProducts() function to get the list of products and assign it to the local products variable.

The removeProduct function will get the productName as input and calls the removeProduct function of ProductService to remove the product from the product list.

Below is the template of the ProductList component.

<div class="container">
  <ng-container *ngIf='products && products.length>0'>
    <ng-container *ngFor='let product of products'>
      <app-product [product]='product' (select)='removeProduct($event)'></app-product>
    </ng-container>
  </ng-container>
</div>

Here we loop through the products list and add the ProductComponent's selector string with product @Input() and select @Output().

In the @Input(), the featured component will provide the product detail to the presentation component which is ProductComponent.

In the @Output() when the ProductComponent emits an event then Product function will be called in ProductListComponent which is the featured component. This will in-turn remove the product from the product list.

If we notice the architecture, the ProductComponent will just raise event and notify the ProductListComponent rather than taking action of its own. So here ProductComponent is a dump component which never perform any business logic.

This architecture is easy to be performed in a small scenario like this but in a complex scenario, like the child component may also have some child component so in such cases, we need to use the smart component to handle communication between the Featured and Presentation components.


Most Read